// 布尔类型变量
// 基本语法格式:
//boolean 变量名 = 初始值;
// 代码示例：
//public class JavaFirst {
//    public static void main(String[] args) {
//        boolean flag = true;
//        System.out.println(flag);
//        // 效果图见图1
//        boolean flag3 = false;
//        System.out.println(flag3);// 附图3
        // 相信大家都是有一定的C语言基础的
        // 在 C语言中，0为假， 非零为真

        //那么我这么写。
//        boolean flag2= 2;
        // 这样写是不行的
        // 在Java当中 boolean 类型，只有 2个取值
        // 要么是 true，要么是 false
        // 附图2

        // 那么 boolean 的值 只能为 ture 和 false
// 我可以这样写吗？
//          boolean flag5 = true +1;
//          boolean flag6 = false+1;
          // 图 4 ，还有一个原因，true 和 false 根本就不是 一个数，所以根本无法相加

//    }
//}




//注意事项:
//        1. boolean 类型的变量只有两种取值, true 表示真, false 表示假.
//        2. Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法.
//        3. boolean 类型有些 JVM 的实现是占 1 个字节, 有些是占 1 个比特位, 这个没有明确规定

// 假如 有一天 你碰到了一道题，有4个选项，让你找出那个是对的（问布尔类型的大小）
// 你看其他三项是不是明确错误的（就是  一个选项 是 1 byte，其它的 都是 几个字节，那就选 1字节的，懂吧）



//  字符串类型变量（字符串类型 是Java特有的类型，不属于 8大基本数据类型）
// 字符串 就是把 一些字符 放到一起
// 基本语法格式：
// String 变量名 = "初始值";
// 代码示例：
//public class JavaFirst {
//    public static void main(String[] args) {
//        String str = "hello";
//        System.out.println(str);// 图 5
//    }
//}
// 知识点， String 是 字符串类型，又称 引用类型

// 在 Java 中 数据类型 主要分为 2部分：
// 数值类型（基本数据类型） ： 整数（byte、short、int、long）、浮点数（float、double）、字符（char）、布尔（boolean）
// 引用类型： String、数组、类、接口、枚举
// 怎么判断 一个变量 是不是 引用类型，你就看这个变量存储的值，是不是一个

// 拓展
//public class JavaFirst {
//    public static void main(String[] args) {
        // 1
//        System.out.println("hello"+"world");// 图 6
        // 从效果图可以看出 它们拼接成一个字符串
        // 也就是说 在 Java 中，两个字符串相加，就能拼接成一个字符串。
        // 即  + 号， 等于 拼接 命令

        // 2
//        System.out.println("hello"+10+20);// 图 7
        // 由 结果得知， 字符串和其它数据类型int 10 和 int 20，使用 + 拼接，其结果就是拼接成一个字符串
        //  语法格式：字符串 + 其他数据类型(将其后的面的数据，不进行处理，转换成字符串，进行拼接)

         // 3
//        System.out.println(10+20+"hello");// 图 8
        // 由结果得知， 其他类型数据int 30  和 字符串，使用 + 拼接
        // 虽然结果还是一个字符串， 但 其他类型的数据，在拼接之前，就已经 处理过了。

        // 4
//        System.out.println(10+""+20+"hello");// 图 9
        // 由结果得知， 当 一个 非字符串类型int 10 与 "" ，使用 + 拼接时，会成为 一个字符串(就相当于 10 带上一个头套)
        // 那么 这就是  第二种情况（ 字符串"10" 和 其他类型数据（int 20） 拼接，其结果还是字符串["1020"]）
        // 和 第一种情况（字符串（"1020"）和 字符串("hello") 拼接）， 其结果 就是 "1020hello"


        // a = 10; b = 20(取巧)
//        System.out.println("a = " + 10 + "; b = " + 20);// 图10
        // 运用了   1  和 2  两种情况
        // 字符串（"a = ")和 其他类型数据 int 10 ，使用 + 号，进行拼接，使其成为一个字符串 “a = 10”
        // 字符串("a = 10") 和 字符串 ("; b = "),使其成为一个字符串“a = 10; b = ”
        // 字符串（"a=10; b="） 和 其他数据类型 int 20，使用 + 号，进行拼接，使其成为一个字符串 "a = 10; b = 20"

//    }
//}

//注意事项:
//        1. Java 使用 双引号 + 若干字符 的方式表示字符串字面值.
//        2. 和上面的类型不同, String 不是基本类型, 而是引用类型(后面重点解释).
//        3. 字符串中的一些特定的不太方便直接表示的字符需要进行转义.





// 转义字符
// 表格自己另外搜索，全一点

// 程序实例
//public class JavaFirst{
//    public static void main(String[] args) {
//        String s1 = "bit";
//        System.out.println(s1);// bit
//
//        // 如果我想输出 "bit",怎么写
////         String s2 = ""bit"";// "bit"? erorr,因为 编译器会认为 两个相邻的发双引号，先结合。将其当做一个整体。图11
//        // 正确写法
//        String s2 = " \"bit\" ";// 这里的 \ 就是转义字符，使上式中，两个相邻的双引号分离。成一个单独双引号
//        // 后面的斜杠也是一样，使其分离成为一个单独的双引号，而这里分离出来的双引号，与bit 结合（"bit"，注意这不是一个字符串，你可以这双引号，看作两个单独的字符），
//        // 最后剩下来的左右最外面的两个双引号，将其（"bit"）转换成 字符串 “ “bit” ”
//        System.out.println(s2);// 图 12
//
//        // 如果我想输出 \bit\
//        //String s3 = "\bit\"; //  结果与s2的错误写法的一样， 双引号 与 \ 结合成一个整体，所以，idea编译器 会提示 在 "\ 的后面缺少一个分号
//                // 图 13
//        //正确写法
//        String s3 = "\\bit\\";// 与s2同理，使两个斜杠与双引号分离，与bit先结合\bit\，最后外面的双引号的作用，是将其(\bit\)当做一个字符串存入 s3
//        System.out.println(s3);// 图14
//
//
//        // 想输出 \\bit\\,就很简单了
//        String s4 = "\\\\bit\\\\";// 一个斜杠管一个字符（斜杠），这每边有 4个斜杠， 所以每边最后剩下 2个斜杠
//        // 最后剩下的两个双引号，将其(\\bit\\)当做一个字符存入 s4
//        System.out.println(s4);
//        // 图 15
//    }
//}




// 变量的作用域
//也就是该变量能生效的范围, 一般是变量定义所在的代码块(定义在大括号里，如果 该变量 出了（不在） 创建它的 大括号里，来到外道大括号外面，该变量就不能使用)

// 讲到这里 我需要提醒一下的是
// 在 Java中 变量 分为两种：
// 1.成员变量；普通成员变量，静态成员变量（在后面讲类和对象的时候，会重点讲解）
// 2.局部变量

// 我们今天所讲的 主要就是 局部变量的作用域
//public class JavaFirst{
          // int b =0; 此时 b 就是成员变量，也就是说，在 类的里面，main方法的外面 定义的变量，称为成员变量
//    public static void main(String[] args) {
//       int a = 10;// a 就是一个局部变量
//    }
//
//    public static void main2(String[] args) {
//        // 注意这 main2， 和 main 完全是两码事，我只是偷个懒，
//        //  public static void func(String[] args) {} 这里 func 和 main2，就是通一个意思
//        System.out.println(a);
//
//    }// 图16
//}


//public class JavaFirst{
//    public static void main(String[] args) {
//        {// 请注意，这只是举例子，这种写法，是不被允许的，以后别写这种代码
//            int a =10;
//        }
//        System.out.println(a);
//        //这样也不行，因为 局部变量 a 的作用域，只在创建它的大括号里能用，出了大括号就不能用
//    }// 图 17
//}


// 接着上一个例子，那如果我这样写呢？
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =0;
//        {
//            a = 99;
//        }
//        System.out.println(a);
//    }// 图 18 ，由图可知，是可以输出a 的值，且a的值为 99，这是因为 a == 99,和输出语句，都在 局部变量 a 的作用域内（在创建局部变量a，所在的大括号里）
//}

// 如何判断变量的作用域？
// 去找 离该变量最近的大括号，该大括号所包含的范围，就是 变量的作用域



// 变量的命名规则

//硬性指标:
//        1. 一个变量名只能包含数字, 字母, 下划线
//        2. 数字不能开头.
//        3. 变量名对大小写很敏感. 即 num 和 Num 是两个不同的变量.
//        注意: 虽然语法上也允许使用中文/美元符($)命名变量, 但是 强烈 不推荐这样做.
//软性指标:
//        1. 变量命名要具有描述性, 见名知意（英文）.
//        2. 变量名不宜使用拼音(但是不绝对,最好别用就对了).
//        3. 变量名的词性推荐使用名词（英文）.
//        4. 变量命名推荐 小驼峰命名法, 当一个变量名由多个单词构成的时候, 除了第一个单词之外, 其他单词首字母都大
//        写.

//public class JavaFirst{
//    public static void main(String[] args) {
//        int 3a = 0;
//        int a3 = 0;
//    }//图19，由图可知 符合 变量的命名规则 硬性指标 第二条 不能以数字开头
//}

//public class JavaFirst{
//    public static void main(String[] args) {
//        int Num = 1;
//        int num = 2;
//        System.out.println(Num);
//        System.out.println(num);
//        //图 20 ，有结果得知 符合 变量命名规则 硬性指标 第三条 变量名对大小写很敏感. 即 num 和 Num 是两个不同的变量.
//    }
//}



// 常量
// 每种类型的变量也对应着一种相同类型的常量.
// 常量指的是运行时类型不能发生改变.

// 常量主要有以下两种体现形式：
//1. 字面值常量
//        10 // int 字面值常量(十进制)
//        010 // int 字面值常量(八进制) 由数字 0 开头. 010 也就是十进制的 8
//        0x10 // int 字面值常量(十六进制) 由数字 0x 开头. 0x10 也就是十进制的 16
//        10L // long 字面值常量. 也可以写作 10l (小写的l)
//        1.0 // double 字面值常量. 也可以写作 1.0d 或者 1.0D
//        1.5e2 // double 字面值常量. 科学计数法表示. 相当于 1.5 * 10^2
//        1.0f // float 字面值常量, 也可以写作 1.0F
//        true // boolen 字面值常量, 同样的还有 false
//        'a' // char 字面值常量, 单引号中只能有一个字符
//        "abc" // String 字面值常量, 双引号中可以有多个字符.



//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;// a 此时是一个变量
//        a = 99;//变量是可以改变的
//        System.out.println(a);
//
//        // 如果在前面加个一个 final
//        final int b = 10;// 是它具有常量属性，不可被改变，这点跟C语言中的const 是一样的功能
//        b = 20;
//        System.out.println(b);
//    }//图21，由图可知， b 现在就相当于是 整形常量，值是无法改变的（另外体现出：常量的值，只能初始化一次，不像变量可以重复赋值）
//    // 另外 我建议常量标识符 用大写好一点,小写也行。你可以认为这是一种默认代码习惯
//    // 即：final int B = 10;
//    // System.out.println(B);// 10
//}



// 小知识点：
// 常量 在程序编译时，就已经确定了其值是什么

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =10;// a 是变量，是在程序运行时，才确定其值是什么
//        final int b =20; // b就是一个常量，它的值，在程序还没有运行之前，在编译阶段就已经确定了其值是什么
//        // 意味着  常量 的 值 确定的速度非常快
//        // 有多快，比变量快（变量已经哭晕在厕所）
//    }
//}




// 类型转换
// java 作为一个强类型编程语言, 当不同类型之间的变量相互赋值的时候, 会有教严格的校验

// int 和 long/double 相互赋值
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =10;
//        long b =20;
//        a=b;// 编译出错，提示 数值精度可能有所损失
//        // 因为 long 8个字节，int是 4个字节，int 肯定是放不下long的
//
//        b=a;// 编译通过
//        // 因为 long 8个字节，int是 4个字节，long肯定是放得下int的。
//
//
//        //有的人可能会说 我一个int类型，怎么可能放不下20，我int类型表示不服！
//        //但你们要明白，你知道，不代表编译器知道，在程序执行之前，系统是不知道你输入数据有多大的
//        // 所以 在Java中，Java为了提高代码的安全性，只要是类型不匹配的值，所占字节大的类型 是无法对 所占字节小的类型，进行赋值的
//        // 而 所占字节小的类型 是可以对 所占字节大的类型进行赋值的。（就是所谓的 大吃小，小吃不下大）
//        // 统统在编译时，不给予通过，程序报错并结束运行。
//        // 其实在编译之前，它就提示你，一个类型所占字节大的 和 另一类型所占字节小的，大的无法对小的进行赋值（图22）
//        // 也就是说 不存在 值的大小 是否存的下,只看类型之间，谁吃谁，大吃小没问题，小吃大，容易被撑死
//        // 这里又在一次体现出 Java 的安全性,也体现出Java是一门强势语言，对类型的检查非常严格
          // 你还程序还没运行，就提示你有错误，你想出错都难
//    }
//}



// 那么 你说，我就像 把 b 的值 存入 a 里面，好的，没问题，这就需要强制类型转换
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =10;
//        long b = 20;
//        a = (int)b;// 把 b 的类型强制类型转换成 int，然后赋给a
//        // 相当于 一个人给你打包票，我做事没问题!
//
//        System.out.println(a);//图 23
//        //结果得知，是可行的
//        // 但是注意一点，任何强制类型转换都是有风险的，你再牛逼也有翻车时候
//    }
//}

// 结论: 不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型, 反之则不行.



 //int 和 boolean 相互赋值
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;
//        boolean b = true;
//        b = a; // 编译出错, 提示不兼容的类型
//        a = b; // 编译出错, 提示不兼容的类型
//   // 因为 boolean 根本就不是一个数字或者说类型都不一样，所以两者根本就无法进行相互赋值
//        // 图 24
//    }
//}

//结论: int 和 boolean 是毫不相干的两种类型, 不能相互赋值



//     int字面值常量 给 byte 赋值

//public class JavaFirst{
//    public static void main(String[] args) {
//        // 注意 byte 的取值范围 -128 ~127
//        byte a = 100; // 编译通过
//
//        // 只要超过 byte 的取值范围，编译器会将 赋给 byte变量的值 认为是另一个类型的值，且比 byte 所占字节大小更大的类型
//        byte b = 256; // 编译报错, 提示 从int转换到byte可能会有损失
//    }// 图25
//}
//结论: 使用字面值常量赋值的时候, Java 会自动进行一些检查校验, 判定赋值是否合理



// 拓展
//public class JavaFirst{
//    public static void main(String[] args) {
//        byte a = 10;
//        byte b = 20;
//        byte c = a+b;
//        // 这样为什么会错呢？
//        // 因为在CPU中，两个类型的数据（类型小于4个字节的数据）在进行运算时，会整形提升
//        // 也就是说 a 与 b，在进行加法运算时，发生整形提升，两者变为了 int 类型的数据
//        // 其结果当然也是 int 类型，所以无法将其运算结果赋给 byte类型的 变量 c
//    }// 图 26
//
//}

//public class JavaFirst{
//    public static void main(String[] args) {
//        byte a =10;
//        byte b =20;
//        byte c = 10+20;
//        System.out.println(c);
//        // 图29，为什么这样写没错？
//        // 因为在 CPU 看来，这就是 两个常量相加，而不是两个变量相加（就该程序而言：如果是两个变量相加，就需要整形提升，其结果数据是int类型）
//        // CPU 将两个常量相加的结果（30） 赋给 一个类型的变量（byte c）
//    }
//}



//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 0;
//        double b = 10.5;
//        a = (int)b;
//        System.out.println(a);
//    }
//}// 图 28

//结论: 使用 (类型) 的方式可以将 double 类型强制转成 int. 但是
//        1. 强制类型转换可能会导致精度丢失. 如刚才的例子中, 赋值之后, 10.5 就变成 10 了, 小数点后面的部分被忽略.
//        2. 强制类型转换不是一定能成功, 互不相干的类型之间无法强转
// 总得来说，只要是强制类型转换，都存在一定风险，正如我上面所说的 你再牛逼也会翻车。


//类型转换小结
//        1. 不同 数字类型 的 变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型
//        （这里不是整形提升，就是单纯的 大吃小：数字类型 所占字节小的变量，它的所有取值，都可以 存储到 比它所占字节更大 的 数字类型 变量 当中）.

//        2. 如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失.
//        3. 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查.



// 理解数值提升

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;
//        long b = 20;
//        int c = a+b;
//        // 这样为什么会错呢？
//        // 因为CPU中，做类型提升时，小的类型会向大的类型进行类型提升（大的类型 所占字节 要大于4字节，否则，提升为整形）
//        // 也就是说 a 与 b，在进行加法运算时，发生类形提升，两者变为了 long 类型的数据
//        // 其结果当然也是 long 类型，所以无法将其运算结果赋给 int 类型的 变量 c
// 需要强制类型转换才能存进去， int c = (int)(a+b);
//    }// 图 27
//
//}


// 整形的意义何在？
// 为了效率高

//类型提升小结:
//        1. 不同类型的数据混合运算, 范围小的会提升成范围大的.
//        2.由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据. 为了硬件上实现方便, 诸如 byte 和 short 这种低于
//4 个字节的类型, 会先提升成 int, 再参与计算




 //int 和 String 之间的相互转换

//  int 转换 字符串
// public class JavaFirst{
//     public static void main(String[] args) {
//         int a = 10;
//         String ret = String.valueOf(a);// valueOf 小驼峰结构，第一个词的首字母不大写，后面的都大写
//         // 这是Java当中，把 数字 转换成 字符串 的方法，
//
//         System.out.println(ret);
//     }
// }// 图30 31


//字符串转换int
//public class JavaFirst{
//    public static void main(String[] args) {
//        String ret = "123";
//        int i = Integer.valueOf(ret);// valueOf 小驼峰结构，第一个词的首字母不大写，后面的都大写
//        // 这是Java当中，把字符串转换成数字的方法，C语言里面用的是 atoi 库函数
//
//        System.out.println(i);
//        // 在这里再讲一次
////        java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类，Integer是java为int提供的封装类
////        Integer提供了多个与整数相关的操作方法，例如，将一个字符串转换成整数，Integer中还定义了表示整数的最大值和最小值的常量
//        // 简单来使 Integer 是一个 类，是 int 的包装类，类里面包含这很多与int相关功能。
//    }
//}// 图32 33



// 运算符


// 算术运算符
// 基本四则运算符 + - * / %


// + - *规则比较简单, 注意的是除法

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 1;
//        int b = 2;
//        System.out.println(a / b);
//        // 结果为 0，为什么呢？不应该是 0.5吗？
//        //因为 两个整数相除，其结果也是整数
//        // 所以 取结果的整数为 0，作为最后结果
//    }// 图 34
//}


 //0 不能作为除数

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =1;
//        int b =0;
//        System.out.println(a/b);
//    }
//}// 图 35，该错误被称为 异常错误（术语）
//// 只要程序抛出 异常错误，程序在异常错误的位置，结束程序的运行


// %  取余(求模/取模，说白了就是取余数)
//public class JavaFirst{
//    public static void main(String[] args) {
//        System.out.println(10%3);
//        // 10 除 3 ，取余 肯定是 1，附图36
//
//        //在 Java中 可以对 小数 求余
//        System.out.println(11.5 % 2);// 图37
//
//    }
//}

// 我赌你们有些人绝对取余会算错下面的题
//public class JavaFirst{
//    public static void main(String[] args) {
//        System.out.println(-10%3);
//        System.out.println(10%-3);
//        System.out.println(-10%-3);
//   // 结果见图 38
//    }
//}



//增量赋值运算符（复合运算符） += -= *= /= %=
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;
//        a+=1;// 等价于 a = a + 1 == 10+1 == 11
//        System.out.println(a);
//        // 图39
//
//        // 但是请注意
//        short s = 10;
//        s= s+1;// 这样写会出错，因为涉及到运算，会进行整形提升，s（这里代表的是常量10，不是变量 s） 和 1 都为 int类型
//        // 其结果也是int类型，所以无法赋给 short类型变量 s
//        // 如果想要 将其结果，强制类型转换
//        s = (short)(s+1);// 图 40
//
//        //但是! 如果使用 符合运算符，奇迹再现
//        s += 1;// 图 41
//        // 由图可知这样写，没有出错。
//        // 因为复合运算符，自带强制类型转换
//    }
//}



//自增/自减运算符 ++ --

// 后置加加
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =10;
//        int b = a++;// 先将a的值(10)赋给 b（b==10），然后自增加1，a == 11
//        System.out.println(a);
//        System.out.println(b);
//    }//图42
//}


// 前置加加
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =10;
//        int b = ++a;// a先自增加1，a == 11，再将其值赋给 b（b==11）
//        System.out.println(a);
//        System.out.println(b);
//    }//图43
//}


// 前置/后置 --
//与 前置/后置 加加 一样

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =10;
//        int b =a--;// 先将a的值 10 赋给 b（b=10），a再自减1 a == 9
//        System.out.println(a);
//        System.out.println(b);
//    }// 图44
//}



//public class JavaFirst{
//    public static void main(String[] args) {
//        int a =10;
//        int b =--a;// a先自减1 a == 9，再将a的值 9 赋给 b（b=9），
//        System.out.println(a);
//        System.out.println(b);
//    }// 图45
//}

//结论:
//        1. 如果不取自增运算的表达式的返回值, 则前置自增和后置自增没有区别.
//        2. 如果取表达式的返回值, 则前置自增的返回值是自增之后的值, 后置自增的返回值是自增之前的值.



//关系运算符（判断数据）
//关系运算符主要有六个:
//  ==   !=    <    >    <=     >=

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;
//        int b = 20;
//        //条件为真，返回 true，否，则返回 false
//        System.out.println(a == b);
//        System.out.println(a != b);
//        System.out.println(a < b);
//        System.out.println(a > b);
//        System.out.println(a <= b);
//        System.out.println(a >= b);
//    }
//}//图46，由结果得知，所有关系运算符的返回值 都是布尔类型数据（true 和 false）

// 拓展
// 在Java中，判断条件是否成立，是根据布尔类型的
//public class JavaFirst{
//    public static void main(String[] args) {
//        if(true)//条件为真，执行if语句
//        {
//            ;
//        }
//        if(false)// 条件为假，不执行if语句
//        {
//            ;
//        }
//        //if(0) 和 if(1)// 这种写法在Java是不存在的
//    }
//}



// 逻辑运算符
//逻辑运算符主要有三个:
//   &&      ||      !
//注意: 逻辑运算符的操作数(操作数往往是关系运算符的结果)和返回值都是 boolean 类型的数据（true 和 false）


// 逻辑与 &&
//规则: 两个操作数都为 true, 结果为 true, 否则结果为 false
// 表达式1 && 表达式2，都为 true, 结果为 true, 否则结果为 false
//而且 逻辑与 支持 短路
// 什么意思呢？ 如果 表达式1 为 假，后面的表达式2就不执行了，因为没必要
// 逻辑或： 双true出true，有false出false
// 有一个false，整个表达式的结果就为 false，所以 表达式2 看与不看（执不执行）都没多大的关系
//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;
//        int b = 20;
//        int c = 30;
//        System.out.println(a < b && b < c);
//        // a确实小于b，b也确实小于 c
//        // 即 双 true 出true
//        //所以输出结果为  true
//    }// 图 47
//}





//逻辑或 ||
//   规则: 两个操作数都为 false, 结果为 false, 否则结果为 true
// 也存在 短路现象
// 表达式1 || 表达式2
// 有 true 出 true，双 false 出 false
// 只要表达式1 为真（true），整个表达式就为true,表达式2 就不用执行了，因为不影响结果

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;
//        int b = 20;
//        int c = 30;
//        System.out.println(a < b || b < c);
//        // a 确实小于 b, a<b 为真（true），整个表达式为 true
//        // 表达式2（b<c） 就没有被执行
//    }
//}// 图48


//逻辑非 !
//     规则: 操作数为 true, 结果为 false; 操作数为 false, 结果为 true(这是个单目运算符, 只有一个操作数).
//public class JavaFirst {
//    public static void main(String[] args) {
//        int a = 10;
//        int b = 20;
////        System.out.println(!a<b);
//        // 由图49可知，!后面跟着不是 boolean 类型的数据
//        // 所以这种写法是错误的
//
//        // 如果是这样写，就没错
//        System.out.println(!(a<b));//图50
//        //因为 所有关系运算符（我们这里是 < ）的返回值 都是布尔类型数据（true 和 false）
//    }
//
//}



// 短路求值
//&& 和 || 遵守短路求值的规则
//        System.out.println(10 > 20 && 10 / 0 == 0); // 打印 false
//        System.out.println(10 < 20 || 10 / 0 == 0); // 打印 true
// 这里值详解 逻辑与，逻辑或 大家可以自己尝试着思考
//public class JavaFirst{
//    public static void main(String[] args) {
//        System.out.println(10>20 && 10/0 == 0);
//        // 大家注意，这个表达式是存在错误的
//        // 除数 是不能为 0的
//        // 那么运行的结果会是如何？
//        //图 51
//    }
//}

//结论
//        1. 对于 && , 如果左侧表达式值为 false,则表达式的整体的值一定是 false, 无需计算右侧表达式
//        2. 对于 ||, 如果左侧表达式值为 true, 则表达式的整体的值一定是 true, 无需计算右侧表达式

// 这样写呢？
//public class JavaFirst{
//    public static void main(String[] args) {
//        System.out.println(10<20 && 10/0 == 0);
//        // 与上不同，这里是小于号，10 确实小于20，所以为真
//        // 继续执行程序
//        // 然后，它才能检测到 除数 是不能为 0的
//        // 那么运行的结果可以想象
//        //图 52
//    }
//}


// &(按位与) 和 |（按位或） (不推荐使用，因为在Java当中使用的太少了，所以大家只需要了解一下就可以了)
// & 和 | 如果操作数为 boolean 的时候, 也表示逻辑运算. 但是和 && 以及 || 相比, 它们不支持短路求值
//  System.out.println(10 > 20 & 10 / 0 == 0); // 程序抛出异常
//  System.out.println(10 < 20 | 10 / 0 == 0); // 程序抛出异常



// 位运算符
//Java 中对数据的操作的最小单位不是字节, 而是二进制位(bit).
//   位运算符主要有四个:
//     &     |      ~      ^
//位操作表示 按二进制位运算. 计算机中都是使用二进制来表示数据的(01构成的序列), 按位运算就是在按照二进制位的每一位依次进行计算.


//按位与 &
// 直接举例子

// 0000 1010
// 0000 1000 上下对应着看，如果两个二进制位都是 1, 则结果为 1, 否则结果为 0
// 0000 1000

//结论
// 一个数的二进制数 与 另一个数的二进制数，相对应的二进制位上的数字，都是1，则结果为1，否则为0
// 假设两个数字 5 和 6，这里我们不写太多，就写 4个bit位，因为它们的数值都不是很大，就不浪费空间了
//5  0101
//6  0110
//   0100 其结果对应的十进制数为 4



// 按位或 |
//如果两个二进制位都是 0, 则结果为 0, 否则结果为 1
// 依然是假设两个数字 5 和 6
//5  0101
//6  0110
//   0111 其结果对应的十进制数为 7

//结论
// 一个数的二进制数 与 另一个数的二进制数，相对应的二进制位上的数字，都是0，则结果为0，否则为1


//注意: 当 & 和 | 的操作数为整数(int, short, long, byte) 的时候, 表示按位运算, 当操作数为 boolean 的时候, 表示逻辑 运算.


//按位异或 ^
// 如果两个数字的二进制位相同, 则结果为 0, 相异则结果为 1
// 依然是假设两个数字 5 和 6
//5  0101
//6  0110
//   0011 其结果对应的十进制数为 3

//按位取反 ~
// 如果该位为 0 则转为 1, 如果该位为 1 则转为 0
// 我这里写一个 32 位 二进制数
// -1的补码
// 1111 1111 1111 1111 1111 1111 1111 1111
// 进行按位取反
// 0000 0000 0000 0000 0000 0000 0000 0000
// 由结果得知：按位取反，是 数值位 和 连符号位一起取反，这一点需要注意

//注意:
//        1. 0x 前缀的数字为 十六进制 数字. 十六进制可以看成是二进制的简化表示方式. 一个十六进制数字对应 4 个二进制位.
//        2. 十六进制的f 表示 10 进制的 15, 也就是二进制的 1111
//        3. printf 能够格式化输出内容, %x 表示按照十六进制输出.
//        4. \n 表示换行符

// 小要求：需掌握 进制 之间转换
// 这个不讲，真要讲的话，而且将每个进制转换都讲清楚的话，感觉要写一篇 万字的博客
//你们自行了解，我就不再增长本文章的长度了


// 移位运算
//移位运算符有三个:
//    <<    >>     >>>
//    都是按照二进制位来运算

// 另外 整数在内存中存的是补码，详细看这篇文章，C语言和Java 这方面是一样的

//左移 <<
//最左侧的二进制位不要了，最右边补一个零
// 例子
// 依然是 5 ，只不过这次是 32位，方便你们理解
// 0000 0000 0000 0000 0000 0000 0000 0101  (5)
// 5 << 1,5的二进制位 左移1位
// 0000 0000 0000 0000 0000 0000 0000 101  (最左侧的零其实已经挤掉了，由于整个二进制数向左移动一位，导致最右边空出一位)
// 最右边空出一位，补0
// 0000 0000 0000 0000 0000 0000 0000 1010 转换成10进制数 为 10


//右移 >>:
//最右侧位不要了, 最左侧补符号位

// 这里我就举6
// 0（最高位/符号位）  000 0000 0000 0000 0000 0000 0000 0110 (6)
// 6 >> 1  6的二进制位 右移1位
//  000 0000 0000 0000 0000 0000 0000 0011(最右侧的零其实已经挤掉了，由于整个二进制数向右移动一位，导致最左边空出一位)
// 补位， 按照原先的6的二进制数的最高位（符号位进行补位），1为负，0为正
// 是 0（正）就补0，是1（负）就补1
// 因为 6 的原先的二进制数的最高位是 0（正），所以我们要补个零
// 0000 0000 0000 0000 0000 0000 0000 0011 转换成10进制数 为 3

// 在假设一个 负数 -1
// 1111 1111 这里我们只写8位
// -1 >> 1
//  111 1111 (最右侧的一其实已经挤掉了，由于整个二进制数向右移动一位，导致最左边空出一位)
//补位， 按照原先的 -1 的二进制数的最高位（符号位进行补位），1为负，0为正
// 是 0（正）就补0，是1（负）就补1
// 因为 -1 的原先的二进制数的最高位是 1（负），所以我们要补个1
// 1111 1111 你会发现


//无符号右移 >>>
// 最右侧位不要了, 最左侧补 0
// 这回特别点，0x ff ff ff ff
// 11111111 11111111 11111111 11111111
//    ff       ff       ff       ff
// 0xffffffff >>> 1,0xffffffff 无符号右移一位
//  1111111 11111111 11111111 11111111
// 最左侧补 0（无符号右移，不管你符号位是0还是1，统一补0）
//   0111 1111 11111111 11111111 11111111
//0x   7   f     f  f    f   f    f  f


// 另外请记住 在Java中是没有 无符号左移的，没有意义
// 左移都是补零，（因为二进制数最右边是没有符号位的，所以统一补0）


//注意:
//        1. 左移 1 位, 相当于原数字 * 2. 左移 N 位, 相当于原数字 * 2 的N次方.
//        2. 右移 1 位, 相当于原数字 / 2. 右移 N 位, 相当于原数字 / 2 的N次方.
//        3. 由于计算机计算移位效率高于计算乘除, 当某个代码正好乘除 2 的N次方的时候可以用移位运算代替.
//        4. 移动负数位或者移位位数过大都没有意义（二进数数只有32位，你要移动35位，没意义）


// 条件运算符
//        条件运算符只有一个:
//        表达式1 ? 表达式2 : 表达式3
//又称 三目运算符
//意思是 表达式1 为真，返回表达式2，为假，返回表达式3
// 意味着 表达式1必须为 布尔表达式

// 举个例子 求两个数的最大值

//public class JavaFirst{
//    public static void main(String[] args) {
//        int a = 10;
//        int b = 20;
//        int max = a > b ? a : b;
//        // 该三目运算符表达的意思是
//        //如果 a大于b为真（true） ，返回 a
//        //否则（a其实是小于b的） 为 假（false），返回b
//
//        // 这里 b 是大于 a的，不满足 a 大于 b的条件
//        // 所以为假（false），返回 b（20）
//        System.out.println(max);
//    }// 图53
//}

//运算符的优先级

//public class JavaFirst{
//    public static void main(String[] args) {
//        System.out.println(1 + 2 * 3);
//    }//结果为 7, 说明先计算了 2*3 , 再计算 1+
//    // 图54
//}

// 如果你想算出 9,用小括号将 1 和 2 括起来
//因为小括号的优先最高，将其括起来，编译器先计算 小括号里的内容
//public class JavaFirst{
//    public static void main(String[] args) {
//        System.out.println((1 + 2) * 3);
//    }//结果为 9, 说明先计算了小括号里 1+2 , 再计算 *3
//    // 图55
//}

//运算符之间是有优先级的. 具体的规则我们不必记忆. 只需要根据自己的逻辑加括号就可以
//小结
//1. % 操作再 Java 中也能针对 double 来计算.
//        2. 需要区分清楚 前置自增 和 后置自增之间的区别.
//        3. 由于 Java 是强类型语言, 因此对于类型检查较严格, 因此像 && 之类的运算操作数必须是 boolean.
//        4. 要区分清楚 & 和 | 什么时候是表示按位运算, 什么时候表示逻辑运算.
//        整体来看, Java 的运算符的基本规则和 C 语言基本一致

